package org.deng.learn.concurrent.basic;

import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author 邓力宾
 * @date 2020/5/15 下午4:46
 * @desc
 * 一、ConcurrentLinkedDeque介绍
 * ConcurrentLinkedDeque 是双向链表结构的无界并发队列。从JDK 7开始加入到J.U.C的行列中。使用CAS实现并发安全，与 ConcurrentLinkedQueue 的区别是该阻塞队列同时支持FIFO和FILO两种操作方式，即可以从队列的头和尾同时操作(插入/删除)。适合“多生产，多消费”的场景。内存一致性遵循对 ConcurrentLinkedDeque 的插入操作先行发生于(happen-before)访问或移除操作。相较于 ConcurrentLinkedQueue，ConcurrentLinkedDeque 由于是双端队列，所以在操作和概念上会更加复杂。
 * 注意：size方法不是一个准确的操作
 *
 * 二、ConcurrentLinkedDeque的一些方法介绍
 * 1、add(E e)：在此deque的尾部插入指定的元素，返回值为Boolean。
 * 2、addFirst(E e)：在此deque前面插入指定的元素。
 * 3、addLast(E e)：在此deque的末尾插入指定的元素。
 * 4、clear()：从这个deque中删除所有的元素。
 * 5、contains(Object o)：返回 true如果这个deque包含至少一个元素 e ，返回值为Boolean。
 * 6、descendingIterator()：以相反的顺序返回此deque中的元素的迭代器，返回值为Iterator。
 * 7、element()：检索但不删除由此deque表示的队列的头部（换句话说，该deque的第一个元素）。
 * 8、getFirst()：检索，但不删除，这个deque的第一个元素。
 * 9、getLast()：检索，但不删除，这个deque的最后一个元素。
 * 10、isEmpty()：如果此集合不包含元素，则返回 true 。
 * 11、iterator()：以正确的顺序返回此deque中的元素的迭代器，返回值为Iterator 。
 * 12、offer(E e)：在此deque的尾部插入指定的元素，返回值为boolean。
 * 13、offerFirst(E e)：在此deque前面插入指定的元素，返回值为boolean。
 * 14、offerLast(E e)：在此deque的末尾插入指定的元素，返回值为boolean。
 * 15、peek()：检索但不删除由此deque表示的队列的头（换句话说，该deque的第一个元素），如果此deque为空，则返回 null 。
 * 16、peekFirst()：检索但不删除此deque的第一个元素，如果此deque为空，则返回 null 。
 * 17、peekLast()：检索但不删除此deque的最后一个元素，如果此deque为空，则返回 null 。
 * 18、poll()：检索并删除由此deque表示的队列的头部（换句话说，该deque的第一个元素），如果此deque为空，则返回 null 。
 * 19、pollFirst()：检索并删除此deque的第一个元素，如果此deque为空，则返回 null 。
 * 20、pollLast()：检索并删除此deque的最后一个元素，如果此deque为空，则返回 null 。
 * 21、pop()：从这个deque表示的堆栈中弹出一个元素。
 * 22、push(E e)：将元素推送到由此deque代表的堆栈（换句话说，在该deque的头部），如果可以立即执行，而不违反容量限制，则抛出 IllegalStateException如果当前没有可用空间）。
 * 23、remove()：检索并删除由此deque表示的队列的头（换句话说，该deque的第一个元素）。
 * 24、remove(Object o)：删除第一个元素 e ，使 o.equals(e) ，如果这样一个元素存在于这个deque，返回值为boolean。
 * 25、removeFirst()：检索并删除此deque的第一个元素。
 * 26、removeFirstOccurrence(Object o)：删除第一个元素 e ，使 o.equals(e) ，如果这样一个元素存在于这个deque，返回值为boolean。
 * 27、removeLast()：检索并删除此deque的最后一个元素。
 * 28、size()：返回此deque中的元素数
 */
public class ConcurrentLinkedDequeDemo {
    //并发容器 队列
    private static Queue<String> tickets = new ConcurrentLinkedDeque<>();
    private static AtomicInteger integer = new AtomicInteger(0); //线程安全的integer
    static {
        for(int i = 0; i < 100; i++){
            tickets.add("票号:"+i);
        }
    }

    public static void main(String[] args){
        CountDownLatch l = new CountDownLatch(10);
        for(int i = 0; i < 10;i++){
            new Thread(()->{
                while (true){
                    String s = tickets.poll();//取元素，取不到返回null 原子操作 线程安全 底层用cas算法实现
                    if(s != null){
                        System.out.println("售票成功:"+s);
                        integer.getAndIncrement();//自增
                    }else{
                        break;
                    }
                }
                l.countDown();
            }).start();
        }
        try {
            l.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("票已售完，共售出："+integer.get()+",剩余:"+tickets.size());
    }
}
